﻿using Microsoft.IdentityModel.Tokens;
using Prism.Commands;
using Prism.Services.Dialogs;
using SmartPlant.Core;
using SmartPlant.Core.Mvvm;
using SmartPlant.Model;
using SmartPlant.Model.Biz;
using SmartPlant.Services.Interfaces;
using SmartPlant.WinCore;
using SmartPlant.WinCore.Config;
using SmartPlant.WinCore.Helper;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace SmartPlantApp.ViewModels
{
    public class LoginViewModel : DialogViewModelBase, IDialogAware
    {
        #region variable
        private string regPath;
        private ServerInfo _serverInfo = null;
        private string _userName = "";
        private string _password = "";
        private ICommand _openFileCommand;
        private ICommand loginCommand;
        private DelegateCommand<object> _pageLoadCommand;
        private DelegateCommand<object> _closeWindowCommand;
        private ObservableCollection<ServerListDto> _serverList;
        private ServerListDto _selectServer;
        private readonly IOAuthService _authService;
        private bool _isSwitchServer = false;
        private string _configId = "";
        private bool _isBusy;
        private bool _isRememberPwd = false;
        private readonly BackgroundWorker backgroundWorker;
        #endregion

        #region binding

        /// <summary>
        /// 服务器列表（对应appsettingsCustom.json里的ConnectionConfigs）
        /// </summary>
        public ObservableCollection<ServerListDto> ServerList
        {
            get
            {
                return _serverList;
            }
            set
            {
                _serverList = value;
            }
        }
        /// <summary>
        /// 列表中选中的
        /// </summary>
        public ServerListDto SelectServer
        {
            get { return _selectServer; }
            set { SetProperty(ref _selectServer, value); }
        }
        /// <summary>
        /// 是否记住密码
        /// </summary>
        public bool RememberPwd
        {
            get { return _isRememberPwd; }
            set { SetProperty(ref _isRememberPwd, value); }
        }

        /// <summary>
        /// 用户
        /// </summary>
        public string UserName
        {
            get { return _userName; }
            set { SetProperty(ref _userName, value); }
        }
        /// <summary>
        /// 密码
        /// </summary>
        public string Pwd
        {
            get { return _password; }
            set { SetProperty(ref _password, value); }
        }
        #endregion


        public LoginViewModel(IOAuthService authService, IDialogService dialog) : base(dialog)
        {
            Title = "系统登陆";
            regPath = WinRegister.regPath;
            _authService = authService;
            backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += this.OnBackgroundWorkerDoWork;
            backgroundWorker.RunWorkerCompleted += OnBackgroundWorkerRunWorkerCompleted;
            OnLoad();
        }

        /// <summary>
        /// 登录按钮触发。isbusy为true后，触发login的代码
        /// </summary>
        public ICommand LoginCommand
        {
            get
            {
                if (loginCommand != null) return loginCommand;
                loginCommand = new DelegateCommand<object>(o => IsBusy = true);
                return loginCommand;
            }
        }

        public ICommand openLogCommand
        {
            get
            {
                if (_openFileCommand != null)
                {
                    return _openFileCommand;//避免资源浪费
                }

                _openFileCommand = new DelegateCommand(() =>
                {
                    string date = DateTime.Now.ToString("yyyy-MM-dd");
                    string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"logs\\{date}");
                    ExplorerFileExtensions.ExplorerFile(dir);
                });
                return _openFileCommand;
            }
        }


        /// <summary>
        /// ？？？
        /// </summary>
        public ICommand CloseWindowCommand
        {
            get
            {
                if (_closeWindowCommand != null) return _closeWindowCommand;
                _closeWindowCommand = new DelegateCommand<object>(o => RaiseRequestClose(new DialogResult(ButtonResult.No)));
                return _closeWindowCommand;
            }
        }

        public ICommand PageLoadCommand
        {
            get
            {
                if (_pageLoadCommand != null) return _pageLoadCommand;
                _pageLoadCommand = new DelegateCommand<object>(OnPageLoadCommand);
                return _pageLoadCommand;
            }
        }


        private async Task<SimpleModel<bool, string>> Login()
        {
            string result = null;
            try
            {
                string configId = _configId;
                if (!_isSwitchServer && _serverInfo != null)
                {
                    string dbType = _serverInfo.Databasetype == "ORA" ? "Oracle" : "SqlServer";
                    configId = $"{_serverInfo.Servername},{_serverInfo.Database},{dbType},{_serverInfo.Username}"; ;
                }

                if (SelectServer != null && SelectServer.ConfigId.IsNotEmptyOrNull())
                {
                    configId = SelectServer.ConfigId;
                    configId = await _authService.SwitchServerAsync(configId);
                }

                var res = await _authService.LoginAsync(new LoginInfo { dynamicConfigId = configId, pwd = _password, user = _userName });
                if (res.succeeded == false)
                {
                    //比如数据库版本太低等
                    return new SimpleModel<bool, string> { v1 = false, v2 = res.errors };
                }
                else
                {
                    result = res.data;
                }
            }
            catch (Exception x)
            {
                var msg = $"系统登陆失败：{x.Message}";
                LoggerHelper.Current.Error(msg, x);
                return new SimpleModel<bool, string> { v1 = false, v2 = msg };
            }

            if (result.IsNullOrEmpty())
            {
                return new SimpleModel<bool, string> { v1 = false, v2 = "登陆失败：未获取到远程服务器授权码！！！" };
            }
            SetUserInfo2Ini();

            GlobalObject.AuthorizationCode = result;
            #region 解析token
            var handler = new JwtSecurityTokenHandler();
            var token = handler.ReadToken(result) as JwtSecurityToken;
            var isSysAdminUser = token.Claims.First(X => X.Type == "SystemAdminFlg").Value.ToString();
            GlobalObject.isSysAdminUser = isSysAdminUser;
            GlobalObject.currentUserID= token.Claims.First(X => X.Type == "Account").Value.ToString();
            GlobalObject.currentUser = token.Claims.First(X => X.Type == "UserId").Value.ToString();
            //GlobalObject.currentUserGroupID = token.Claims.First(X => X.Type == "UserGroupID").Value.ToString();


            #endregion
            return new SimpleModel<bool, string> { v1 = true, v2 = "登陆成功。" };
        }

        /// <summary>
        /// 当前是否处理忙碌状态。
        /// </summary>
        public bool IsBusy
        {
            get { return _isBusy; }
            set
            {
                if (this._isBusy != value)
                {
                    this._isBusy = value;
                    if (_isBusy && UserName.IsNullOrEmpty())
                    {
                        Dialog.ShowAltert("请输入需要登录的用户名！！！");
                        _isBusy = false;
                        return;
                    }
                    if (_isBusy && Pwd.IsNullOrEmpty())
                    {
                        Dialog.ShowAltert("请输入需要登录的用户密码！！！");
                        _isBusy = false;
                        return;
                    }

                    this.OnPropertyChanged(nameof(IsBusy));

                    if (this._isBusy && !backgroundWorker.IsBusy)
                    {
                        backgroundWorker.RunWorkerAsync();//真正的login是在这个里面的
                    }
                    else
                    {
                        this._isBusy = false;
                        this.OnPropertyChanged(nameof(IsBusy));
                    }
                }
            }
        }
        /// <summary>
        /// 里面放一个异步的耗时操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            var task = Login();
            while (!task.IsCompleted)
            {
                Thread.Sleep(1000);
            }
            e.Result = task.Result;
        }
        /// <summary>
        /// RunWorkerCompleted 事件处理函数会在DoWork 事件处理函数返回后被调用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            InvokeOnUIThread(() =>
            {
                var result = e.Result as SimpleModel<bool, string>;
                this.IsBusy = false;
                if (result != null && result.v1)
                {
                    RaiseRequestClose(new DialogResult(ButtonResult.OK));
                    return;
                }
                else
                {
                    Dialog.ShowAltert(result.v2);
                    //RaiseRequestClose(new DialogResult(ButtonResult.None));
                    return;
                }
            });
        }

        #region Load
        private void OnPageLoadCommand(object obj)
        {
            if (_isSwitchServer)
            {
                Dialog.ShowQuestion("系统未找到intools.ini配置文件，点击【是】将使用服务器上已有的配置进行数据库连接，点击【否】将退出系统，请检查SPI安装环境。", r =>
                {
                    if (r.Result == ButtonResult.Yes)
                    {
                        Dialog.ShowDialog("ServerSwitch", d =>
                        {
                            if (d.Result != ButtonResult.OK)
                            {
                                Application.Current.Shutdown();
                            }
                            else
                            {
                                _configId = d.Parameters.GetValue<string>("configId");
                            }
                        });
                    }
                    else
                    {
                        Application.Current.Shutdown();
                    }
                });
            }
        }

        private async void OnLoad()
        {
            ServerList = new ObservableCollection<ServerListDto>();
            /*
            string path = GetIniFilePath();
            _serverInfo = GetServerInfo(path);
            if (_serverInfo != null)
            {
                await _authService.GetServerInfoAsync(_serverInfo);
            }
            */
            GetUserPwd();
            CheckServerAddr();

            try
            {
                var configs = await _authService.GetConfigsAsync();
                ServerList.Clear();
                if (configs != null && configs.Count > 0)
                {
                    var list = new List<ServerListDto>();
                    foreach (var config in configs)
                    {
                        var serName = config.dbType == "1" ? "Sql Server" : config.dbType == "0" ? "MySql" : "Oracle";
                        list.Add(new ServerListDto { ConfigId = config.configId, DbType = config.dbType, DbTypeName = serName });
                    }
                    ServerList.AddRange(list);
                }
            }
            catch (Exception x)
            {
                Dialog.ShowAltert($"获取远程服务器配置信息失败：{x.Message}，请重新配置服务器地址！！！！");
                ConfigServer();
            }
        }
        /// <summary>
        /// 地址不合适 就弹出服务器测试界面
        /// </summary>
        private void CheckServerAddr()
        {
            if (GlobalObject.CurrentConfig != null && GlobalObject.CurrentConfig.ServerAddress.IsNotEmptyOrNull())
            {
                return;
            }
            ConfigServer();
        }
        /// <summary>
        /// 准备弹出服务器配置地址窗口
        /// </summary>
        private void ConfigServer()
        {
            Dialog.ShowDialog("ServerSetting", r =>
            {
                if (r.Result == ButtonResult.Cancel)
                {
                    Environment.Exit(0);
                }
                var config = ConfigHelper.ReadConfig();
                GlobalObject.CurrentConfig = config;
            });
        }


        //private ServerInfo GetServerInfo(string iniFile)
        //{
        //    if (iniFile.IsNullOrEmpty())
        //        return null;
        //    var initFile = iniFile.CombinePath("intools.ini");
        //    if (!File.Exists(initFile))
        //    {
        //        LoggerHelper.Current.Error($"ini配置文件路径：{initFile} 不存在，需要进行服务切换！！！");
        //        _isSwitchServer = true;
        //        return null;
        //    }

        //    var config = Configuration.LoadFromFile(iniFile.CombinePath("intools.ini"));
        //    var section = config["PROFILES"];
        //    if (section == null)
        //        throw new ArgumentNullException(nameof(section));

        //    var serverNameSetting = section["DEFAULT"];
        //    if (serverNameSetting == null)
        //        throw new ArgumentNullException(nameof(serverNameSetting));
        //    var serverName = serverNameSetting.StringValue;
        //    //LoggerHelper.Current.Info($"DEFAULT默认Profilename配置值：{serverName}");

        //    var serverSection = config[serverName];
        //    if (serverSection == null)
        //        throw new ArgumentNullException(nameof(serverSection));
        //    var serverInfo = new ServerInfo
        //    {
        //        Profilename = serverName,
        //        Servername = serverSection["ServerName"].StringValue,
        //        Database = serverSection["Database"].StringValue,
        //        Username = serverSection["LogId"].StringValue,
        //        Password = serverSection["LogPassword"].StringValue,
        //        Databasetype = serverSection["DBMS"].StringValue,
        //        Port = "1521"
        //    };

        //    //LoggerHelper.Current.Info($"Servername配置值：{serverInfo.Servername}");
        //    //LoggerHelper.Current.Info($"Database配置值：{serverInfo.Database}");
        //    //LoggerHelper.Current.Info($"Username配置值：{serverInfo.Username}");
        //    //LoggerHelper.Current.Info($"Password配置值：{serverInfo.Password}");
        //    //LoggerHelper.Current.Info($"Databasetype配置值：{serverInfo.Databasetype}");
        //    //LoggerHelper.Current.Info($"Port配置值：{serverInfo.Port}");
        //    LoggerHelper.Current.Info($"成功读取系统配置文件：{initFile}");
        //    return serverInfo;
        //}

        //private string GetIniFilePath()
        //{
        //    string curVer = "";
        //    WinRegister.GetStringValueKey(regPath, "CurVer", ref curVer, "");
        //    if (curVer.IsNullOrEmpty())
        //    {
        //        _isSwitchServer = true;
        //        return null;
        //    }
        //    string path = "";
        //    WinRegister.GetStringValueKey(regPath + "\\" + curVer, "Path", ref path, "");
        //    LoggerHelper.Current.Info($"从注册表路径{regPath}成功读配置文件路径信息。");
        //    return path;
        //}
        /// <summary>
        /// 写入登录信息到配置文件
        /// </summary>
        private void SetUserInfo2Ini()
        {
            SysConfig sysConfig = ConfigHelper.ReadConfig();
            sysConfig.LoginName = "";
            sysConfig.LoginPwd = "";
            sysConfig.RememberPwd = 01;
            if (_isRememberPwd)
            {
                sysConfig.LoginName = UserName;
                sysConfig.LoginPwd = DESCEncryption.Encrypt(Pwd);
                sysConfig.RememberPwd = 1;
            }
            ConfigHelper.WriteConfig(sysConfig);
        }
        /// <summary>
        /// 从配置文件拿密码
        /// </summary>
        private void GetUserPwd()
        {
            SysConfig sysConfig = ConfigHelper.ReadConfig();

            string loginName = sysConfig.LoginName;
            string pwd = sysConfig.LoginPwd;
            string isRememberPwd = sysConfig.RememberPwd.ToString();
            UserName = loginName;
            RememberPwd = isRememberPwd == "1";
            try
            {
                Pwd = pwd.IsNullOrEmpty() ? "" : DESCEncryption.Decrypt(pwd);
            }
            catch
            {
                Pwd = "";
            }
        }
        #endregion
    }
}
